﻿using CuaHangLego.DataAccess;
using CuaHangLego.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinqEx
{
    class Program
    {
        static void Main(string[] args)
        {
            IList<SanPham> listSP = SanPhamDA.Instance.GetAll();
            SanPham[] linqSP = listSP.ToArray<SanPham>();

            IList<ChuDe> listCD = ChuDeDA.Instance.GetAll();
            ChuDe[] linqCD = listCD.ToArray<ChuDe>();

            //var data1 = linq1.Where((sp, index) => sp.GiaBan > 700000 & index > 3);
            //var data1 = from n in linq1
            //            select new { upper = n.Ten.ToUpper(), lower = n.Ten.ToLower() };
            //var data1 = from cd in linqCD
            //            from sp in linqSP
            //            where sp.ChuDe.MaSo == cd.MaSo
            //            select sp;
            //var data1 = linqCD.SelectMany(cd => from sp in linqSP where sp.ChuDe.MaSo == cd.MaSo select sp);
            //var data1 = linqSP.Take(5);
            //var data1 = linqSP.Skip(5).Take(3);
            //var data1 = linqSP.TakeWhile((sp, index) => index < 5);
            //var data1 = linqSP.SkipWhile(sp => sp.ChuDe.MaSo < 2);
            //var data1 = from sp in linqSP
            //            orderby sp.GiaBan descending
            //            select sp;
            //var data1 = linqSP.OrderBy(sp => sp.Ten);
            //var data1 = linqSP.OrderByDescending(sp => sp.Ten);
            //var data1 = from sp in linqSP
            //            orderby sp.GiaBan descending, sp.Ten
            //            select sp;
            //var data1 = linqSP.OrderBy(sp => sp.GiaBan).ThenBy(sp => sp.Ten);


            //foreach (var e in data1)
            //{
            //    Console.WriteLine(string.Format("{0}\t{1}\t{2}", e.MaSo, e.Ten, e.GiaBan));
            //}

            //var data = from sp in linqSP
            //           group sp by sp.ChuDe.MaSo into g
            //           select new { cdgroup = g.Key, items = g };
            //foreach (var g in data)
            //{
            //    Console.WriteLine(string.Format("ChuDe {0}", g.cdgroup));
            //    foreach(var sp in g.items)
            //    {
            //        Console.WriteLine(string.Format("SanPham {0}", sp.Ten));
            //    }
            //}

            //var data = from sp in linqSP
            //           group sp by sp.NgaySX.Year into y
            //           select new
            //           {
            //               year = y.Key,
            //               items_y = from sp2 in y
            //                         group sp2 by sp2.NgaySX.Month into m
            //                         select new
            //                         {
            //                             month=m.Key,
            //                             items_m = m
            //                         }
            //           };
            //foreach (var y in data)
            //{
            //    Console.WriteLine("-------------------------------------");
            //    Console.WriteLine("Year:\t" + y.year);
            //    foreach (var m in y.items_y)
            //    {
            //        Console.WriteLine("\nMonth:\t" + m.month);
            //        foreach (var sp in m.items_m)
            //        {
            //            Console.WriteLine(string.Format("SanPham: {0}\t{1}", sp.Ten, sp.NgaySX));
            //        }
            //    }
            //}

            //var data = linqSP.GroupBy(w => w.ChuDe.Ten, new AnagramEqualityComparer());

            //int[] a = new int[] { 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0 };
            //var data = a.Distinct();
            //foreach (var i in data)
            //{
            //    Console.Write("\t" + i);
            //}

            //var data = linqSP.Select(sp => sp.ChuDe.Ten).Distinct();
            //foreach (var e in data)
            //{
            //    Console.WriteLine(string.Format("{0}", e));
            //}

            //int[] numA = { 1, 2, 3, 4, 7, 9 };
            //int[] numB = { 0, 2, 3, 5, 7, 10 };
            //var data = numA.Union(numB).Distinct().OrderBy(i => i);
            //foreach (var i in data)
            //{
            //    Console.Write("\t" + i);
            //}
            
            //int[] numA = { 1, 2, 3, 4, 7, 9 };
            //int[] numB = { 0, 2, 3, 5, 7, 10 };
            //var data = numA.Intersect(numB).Distinct().OrderBy(i => i);
            //foreach (var i in data)
            //{
            //    Console.Write("\t" + i);
            //}

            //int[] numA = { 1, 2, 3, 4, 7, 9 };
            //int[] numB = { 0, 2, 3, 5, 7, 10 };
            //var data = numA.Except(numB).Distinct().OrderBy(i => i);
            //foreach (var i in data)
            //{
            //    Console.Write("\t" + i);
            //}

            //object[] numbers = { null, 1.0, "two", 3, "four", 5, "six", 7.0 };

            //var doubles = numbers.OfType<double>();

            //Console.WriteLine("Numbers stored as doubles:");
            //foreach (var d in doubles)
            //{
            //    Console.WriteLine(d);
            //} 

            //var data = listSP.FirstOrDefault(sp => sp.Ten.Contains("City"));
            //Console.WriteLine(string.Format("{0}", data != null ? data.Ten : "NIL"));

            //var data = listSP.Any(sp => sp.Ten.Contains("City"));
            //Console.WriteLine(string.Format("{0}", data ? "True" : "False"));

            //var data = listSP.All(sp => sp.Ten.Contains("LEGO"));
            //Console.WriteLine(string.Format("{0}", data ? "True" : "False"));
            
            //var data = linqSP.Sum(sp=>sp.GiaBan);
            //Console.WriteLine("Sum of GIABAN: " + data);
            
            //var data = from sp in linqSP
            //           group sp by sp.ChuDe.MaSo into g
            //           select new { gname = g.Key, gsum = g.Sum(sp => sp.GiaBan) };
            //foreach (var e in data)
            //{
            //    Console.WriteLine(string.Format("Group {0} has sum: {1}", e.gname, e.gsum));
            //}

            //var data = from sp in linqSP
            //           group sp by sp.ChuDe.MaSo into g
            //           select new { gname = g.Key, gsum = g.Min(sp => sp.GiaBan) };
            //foreach (var e in data)
            //{
            //    Console.WriteLine(string.Format("Group {0} has min: {1}", e.gname, e.gsum));
            //}

            //var data = from sp in linqSP
            //           group sp by sp.ChuDe.MaSo into g
            //           let minGia = g.Min(sp => sp.GiaBan)
            //           select new { gname = g.Key, gcheapestproduct = g.Where(sp => sp.GiaBan == minGia) };
            //foreach (var e in data)
            //{
            //    Console.WriteLine(string.Format("Group: {0}", e.gname));
            //    foreach (var sp in e.gcheapestproduct)
            //    {
            //        Console.WriteLine(string.Format("Product: {0}", sp.Ten));
            //    }
            //}

            //int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

            //int i = 0;
            //var q =
            //    from n in numbers
            //    select ++i;

            //// Note, the local variable 'i' is not incremented 
            //// until each element is evaluated (as a side-effect): 
            //foreach (var v in q)
            //{
            //    Console.WriteLine("v = {0}, i = {1}", v, i);
            //}

            //var data = from cd in listCD
            //           join sp in listSP on cd.MaSo equals sp.ChuDe.MaSo
            //           select new { pname = sp.Ten, cdname = cd.Ten };
            //foreach (var e in data)
            //{
            //    Console.WriteLine("{0}:{1}", e.pname, e.cdname);
            //}

            Console.WriteLine("\n-------------------------------------");
            Console.ReadKey();
        }

        public class AnagramEqualityComparer : IEqualityComparer<string>
        {
            public bool Equals(string x, string y)
            {
                return getCanonicalString(x) == getCanonicalString(y);
            }

            public int GetHashCode(string obj)
            {
                return getCanonicalString(obj).GetHashCode();
            }

            private string getCanonicalString(string word)
            {
                char[] wordChars = word.ToCharArray();
                Array.Sort<char>(wordChars);
                return new string(wordChars);
            }
        } 
    }
}
